﻿Imports System.IO
Imports System.ComponentModel
Imports System.Security.Permissions
Public Class PhotoSorter
    Private Sub PhotoSorter_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        btnCancel.Visible = False
        cmbFileTypes.SelectedItem = "All"
        txtFileTypes.ReadOnly = True
    End Sub
    Private Sub btnSrcBrowse_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSrcBrowse.Click
        FolderBrowserDialog1.ShowDialog()
        If txtSrcPath.Text = "" Then
            txtSrcPath.Text = FolderBrowserDialog1.SelectedPath
        Else
            txtSrcPath.Text += ";" & FolderBrowserDialog1.SelectedPath
        End If

    End Sub

    Private Sub btnDestBrowse_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDestBrowse.Click
        FolderBrowserDialog1.ShowDialog()
        txtDestPath.Text = FolderBrowserDialog1.SelectedPath
    End Sub
    Private Sub chkCreateSubfolders_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chkCreateSubfolders.CheckedChanged
        If chkCreateSubfolders.Checked Then
            rdoCreatedOn.Enabled = True
            rdoModifiedOn.Enabled = True
        Else
            rdoCreatedOn.Enabled = False
            rdoModifiedOn.Enabled = False
        End If
    End Sub
    Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.Click

        If FormValidations() = True Then
            'We cannot start more then one calculation at a single time
            btnStart.Visible = False
            'We can now cancel the process
            btnCancel.Visible = True
            'Reset some other controls 
            ProgressBar1.Value = 0
            lblStatus.Text = "Processing your request..... please wait"
            Me.Cursor = Cursors.WaitCursor

            Dim Args(11) As Object
            Args(0) = txtDestPath.Text
            Args(1) = txtSrcPath.Text
            Args(2) = rdoMove.Checked
            Args(3) = ""
            Args(4) = txtFileTypes.Text
            Args(5) = chkCreateSubfolders.Checked
            Args(6) = rdoCreatedOn.Checked
            Args(7) = rdoModifiedOn.Checked
            Args(8) = rdoRenameFile.Checked
            Args(9) = txtRenamePrefix.Text
            Args(10) = rdoDuplicateOverwrite.Checked


            Me.BackgroundWorker1.WorkerReportsProgress = True
            Me.BackgroundWorker1.WorkerSupportsCancellation = True
            Me.BackgroundWorker1.RunWorkerAsync(Args)
        End If
    End Sub
    Private Sub cmbFileTypes_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmbFileTypes.SelectedIndexChanged
        If cmbFileTypes.SelectedItem = "All" Then
            txtFileTypes.Text = "*.*"
            txtFileTypes.ReadOnly = True
        End If
        If cmbFileTypes.SelectedItem = "Photos" Then
            txtFileTypes.Text = "*.jpg;*.png;*.bmp;*.jpeg;*.raw;*.gif"
            txtFileTypes.ReadOnly = True
        End If
        If cmbFileTypes.SelectedItem = "Videos" Then
            txtFileTypes.Text = "*.avi;*.mp4;*.mov;*.wmv;*.mpg"
            txtFileTypes.ReadOnly = True
        End If
        If cmbFileTypes.SelectedItem = "Photos and Videos" Then
            txtFileTypes.Text = "*.jpg;*.png;*.bmp;*.jpeg;*.raw;*.gif;*.avi;*.mp4;*.mov;*.wmv;*.mpg"
            txtFileTypes.ReadOnly = True
        End If
        If cmbFileTypes.SelectedItem = "Custom" Then
            txtFileTypes.Text = "*.wav"
            txtFileTypes.ReadOnly = False
        End If

    End Sub
    Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        'Never manipulate any Windows Forms controls here
        Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
        Dim arr() As Object = CType(e.Argument, Object)
        e.Result = Async_CopyFiles(arr, worker, e)
    End Sub

    Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
        ProgressBar1.Value = e.ProgressPercentage
    End Sub

    Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
        'Check the state of completion
        If Not (e.Error Is Nothing) Then
            'an error occured and stopped the calculation
            lblStatus.Text = e.Error.Message
        ElseIf e.Cancelled Then
            'the process was cancelled by the user
            lblStatus.Text = "Process cancelled"
        Else
            'the process completed normally
            lblStatus.Text = "Files " & IIf(rdoCopy.Checked, "copied", "moved") & " successfully" ' & e.Result.ToString
        End If
        'Reset some other controls 
        btnStart.Visible = True
        btnCancel.Visible = False
        Me.Cursor = Cursors.Default
    End Sub
    
    Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click
        BackgroundWorker1.CancelAsync()
    End Sub

    Private Sub PhotoSorter_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        'in case the process is still running when the form is about to be closed.
        If BackgroundWorker1.IsBusy Then
            BackgroundWorker1.CancelAsync()
        End If
    End Sub
    Private Function FormValidations() As Boolean


        'Source and Destination should be entered
        If Trim(txtSrcPath.Text) = "" Then
            lblStatus.Text = "Source path cannot be empty"
            Return False
        End If
        If Trim(txtDestPath.Text) = "" Then
            lblStatus.Text = "Destination path cannot be empty"
            Return False
        End If

        'If FileType ONLY is checked then something should be entered in the wildcard text box
        If cmbFileTypes.SelectedItem = "Custom" And Trim(txtFileTypes.Text) = "" Then
            lblStatus.Text = "Custom file types cannot be empty"
            Return False
        End If

        Return True
    End Function
    Private Function Async_CopyFiles(ByVal Arr() As Object, ByVal pWorker As BackgroundWorker, ByVal e As DoWorkEventArgs)
        Dim ArrSrcPaths As String()
        Dim fileList As String()
        Dim SrcFolderPath As String
        Dim DestFolderPath As String
        Dim i As Integer
        Dim Status As String = ""
        Dim FilterList As String = "*.*"
        Dim SourceFileName As String = ""
        Dim DestFileNameWithPath As String = ""
        Dim DestFileNamePrefix As String = ""
        Dim CreateSubFoldersBy As String = ""
        Dim SubFoldersName As String = ""
        Dim ArrSrcPathFolder As String()
        Dim RenameOrOverwrite As String = "Rename"
        Dim MoveOrCopy As String = "Copy"
        Dim NewDestFolderPath As String = ""
        Dim OriginalfilenameOrRename As String = "Original"
        Dim RenamePrefix As String = ""
        Dim NumberOfFilesToCopy As Int64
        Dim CurrentFileNumber As Int64 = 0

        Dim rdoMove As Boolean
        Dim txtFileTypes As String
        Dim chkCreateSubfolders As Boolean
        Dim rdoCreatedOn As Boolean
        Dim rdoModifiedOn As Boolean
        Dim rdoRenameFile As Boolean
        Dim txtRenamePrefix As String
        Dim rdoDuplicateOverwrite As Boolean


        DestFolderPath = CType(Arr(0), String)
        ArrSrcPaths = CType(Arr(1), String).Split(";")
        rdoMove = CType(Arr(2), Boolean)
        txtFileTypes = CType(Arr(4), String)
        chkCreateSubfolders = CType(Arr(5), Boolean)
        rdoCreatedOn = CType(Arr(6), Boolean)
        rdoModifiedOn = CType(Arr(7), String)
        rdoRenameFile = CType(Arr(8), Boolean)
        txtRenamePrefix = CType(Arr(9), String)
        rdoDuplicateOverwrite = CType(Arr(10), Boolean)

        If rdoMove Then MoveOrCopy = "Move"
        If rdoCreatedOn And chkCreateSubfolders Then CreateSubFoldersBy = "CreatedOn"
        If rdoModifiedOn And chkCreateSubfolders Then CreateSubFoldersBy = "ModifiedOn"
        If rdoDuplicateOverwrite Then RenameOrOverwrite = "Overwrite"
        If rdoRenameFile Then OriginalfilenameOrRename = "Rename"
        RenamePrefix = txtRenamePrefix
        NewDestFolderPath = DestFolderPath
        FilterList = txtFileTypes

        If pWorker.CancellationPending = True Then
            e.Cancel = True
        Else
            For i = 0 To ArrSrcPaths.GetLength(0) - 1
                SrcFolderPath = ArrSrcPaths.GetValue(i)
                Try

                    'Dim fP As New FileIOPermission(System.Security.Permissions.PermissionState.None)
                    'fP.AllLocalFiles = FileIOPermissionAccess.Read
                    'fP.Demand()

                    fileList = MyGetFiles(SrcFolderPath, FilterList, SearchOption.AllDirectories)
                    NumberOfFilesToCopy = fileList.Length

                    For Each SourceFileNameWithPath As String In fileList
                        If pWorker.CancellationPending = True Then
                            e.Cancel = True
                        Else
                            CurrentFileNumber = CurrentFileNumber + 1

                            'Status = MoveOrCopy & "ing file : " & SourceFileNameWithPath
                            If CreateSubFoldersBy = "CreatedOn" Then
                                SubFoldersName = Format(File.GetCreationTime(SourceFileNameWithPath), "yyyy_MM_dd")
                            ElseIf CreateSubFoldersBy = "ModifiedOn" Then
                                SubFoldersName = Format(File.GetLastWriteTime(SourceFileNameWithPath), "yyyy_MM_dd")
                            End If

                            If SubFoldersName <> "" Then
                                NewDestFolderPath = DestFolderPath & "\" & SubFoldersName
                            End If

                            If Not Directory.Exists(NewDestFolderPath) Then
                                Directory.CreateDirectory(NewDestFolderPath)
                            End If

                            ArrSrcPathFolder = SourceFileNameWithPath.Split("\")
                            SourceFileName = ArrSrcPathFolder(ArrSrcPathFolder.GetLength(0) - 1)

                            DestFileNamePrefix = ""
                            If OriginalfilenameOrRename = "Rename" Then
                                DestFileNamePrefix = RenamePrefix
                                If DestFileNamePrefix.Contains("%FileDate%") Then
                                    DestFileNamePrefix = DestFileNamePrefix.Replace("%FileDate%", Format(File.GetLastWriteTime(SourceFileNameWithPath), "yyyy_MM_dd"))
                                End If
                            End If
                            DestFileNameWithPath = NewDestFolderPath & "\" & DestFileNamePrefix & SourceFileName


                            If File.Exists(DestFileNameWithPath) And RenameOrOverwrite = "Rename" Then
                                DestFileNamePrefix = "Copy " & Int(Rnd() * Now.Millisecond) & " of_" & DestFileNamePrefix
                                DestFileNameWithPath = NewDestFolderPath & "\" & DestFileNamePrefix & SourceFileName
                            End If


                            If File.Exists(DestFileNameWithPath) And RenameOrOverwrite = "Overwrite" Then
                                If File.GetLastWriteTime(SourceFileNameWithPath) >= File.GetLastWriteTime(DestFileNameWithPath) Then
                                    File.SetAttributes(DestFileNameWithPath, FileAttributes.Normal)
                                    File.Delete(DestFileNameWithPath)
                                Else
                                    File.Delete(SourceFileNameWithPath)
                                    pWorker.ReportProgress(CInt(CurrentFileNumber / NumberOfFilesToCopy * 100))
                                    Exit For
                                End If
                            End If


                            If MoveOrCopy = "Move" Then
                                File.Move(SourceFileNameWithPath, DestFileNameWithPath)
                            Else
                                File.Copy(SourceFileNameWithPath, DestFileNameWithPath)
                            End If

                            pWorker.ReportProgress(CInt(CurrentFileNumber / NumberOfFilesToCopy * 100))
                        End If
                    Next
                Catch dirNotFound As DirectoryNotFoundException
                    MsgBox(dirNotFound.Message)
                End Try

            Next
            pWorker.ReportProgress(100)
        End If
        Return Status
    End Function
    Public Function MyGetFiles(ByVal SourceFolder As String, ByVal Filter As String, ByVal searchOption As System.IO.SearchOption) As String()
        ' ArrayList will hold all file names
        Dim alFiles As ArrayList = New ArrayList()

        ' Create an array of filter string
        Dim MultipleFilters() As String = Filter.Split(";")

        ' for each filter find mathing file names
        For Each FileFilter As String In MultipleFilters
            ' add found file names to array list
            alFiles.AddRange(Directory.GetFiles(SourceFolder, FileFilter, searchOption))
        Next

        ' returns string array of relevant file names
        Return alFiles.ToArray(Type.GetType("System.String"))
    End Function






   
End Class


